package com.iwhalecloud.citybrain.flow.platform.manager.application.service.impl;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.iwhalecloud.citybrain.flow.platform.manager.application.common.context.FlowElementProcessContext;
import com.iwhalecloud.citybrain.flow.platform.manager.application.service.CustomPropertiesProcessor;
import com.iwhalecloud.citybrain.flow.platform.manager.application.utils.JsonUtils;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.eventconfig.DeployedEventConfigDomain;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.model.eventconfig.NodeEventConfigRawDTO;
import com.iwhalecloud.citybrain.flow.platform.manager.domain.repository.FlowEventConfigRepository;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.common.api.delegate.event.FlowableEngineEventType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author lilh
 * @date 2021/3/1 14:13
 */
@Component
public class EventConfigPropertiesProcessor implements CustomPropertiesProcessor {

    @Autowired
    private FlowEventConfigRepository eventConfigRepository;

    @Override
    public boolean support(JsonNode elementNode) {
        JsonNode properties = elementNode.get("properties");
        if (nonNull(properties)) {
            return nonNull(properties.get("eventConfig")) && properties.get("eventConfig").size()!=0;
        }
        return false;
    }

    @Override
    public void process(FlowElementProcessContext context) {
        List<DeployedEventConfigDomain> eventConfig = resolveEventConfig(context);
        for (DeployedEventConfigDomain config : eventConfig) {
            eventConfigRepository.insertEventConfig(config);
        }
    }

    private List<DeployedEventConfigDomain> resolveEventConfig(FlowElementProcessContext context) {
        List<DeployedEventConfigDomain> result = new ArrayList<>();
        JsonNode eventConfigNode = context.getElementNode().get("properties").get("eventConfig");
        List<NodeEventConfigRawDTO> nodeEventConfigRawDTOS = JsonUtils.toObject(
                JsonUtils.toJson(eventConfigNode), new TypeReference<List<NodeEventConfigRawDTO>>(){});
        if (nodeEventConfigRawDTOS == null) {
            return result;
        }
        String multiinstanceType = null;
        if (context.getElementNode().get("properties").has("multiinstance_type")){
            multiinstanceType = context.getElementNode().get("properties").get("multiinstance_type").textValue();
        }
        for (NodeEventConfigRawDTO node : nodeEventConfigRawDTOS) {
            DeployedEventConfigDomain temp = new DeployedEventConfigDomain();
            temp.setName(node.getName());
            temp.setDescription(node.getDesc());
            if ("Parallel".equalsIgnoreCase(multiinstanceType) || "Sequential".equalsIgnoreCase(multiinstanceType)) {
                String eventType = node.getEventType();
                if (Objects.equals(eventType,FlowableEngineEventType.TASK_CREATED.name())){
                    temp.setEventType(FlowableEngineEventType.MULTI_INSTANCE_ACTIVITY_STARTED.name());
                }else if (Objects.equals(eventType,FlowableEngineEventType.TASK_COMPLETED.name())){
                    temp.setEventType(FlowableEngineEventType.MULTI_INSTANCE_ACTIVITY_COMPLETED_WITH_CONDITION.name());
                }else{
                    temp.setEventType(eventType);
                }
            } else {
                temp.setEventType(node.getEventType());
            }
            Map.Entry<String, String> config = node.getConfig();
            if (Objects.nonNull(config)) {
                temp.setCallbackType(config.getKey());
                temp.setCallbackContent(config.getValue());
            }
            String callMethod = "sync";
            if (StringUtils.isNotBlank(node.getCallMethod())){
                callMethod = node.getCallMethod();
            }
            temp.setCallMethod(callMethod);
            temp.setCallbackParam(node.getCallbackParam());
            temp.setRequestBody(node.getRequestBody());
            temp.setModelId(context.getModelNode().get("modelId").textValue());
            temp.setModelKey(context.getModelNode().get("properties").get("process_id").textValue());
            temp.setModelName(context.getModelNode().get("properties").get("name").textValue());
            temp.setNodeCode(context.getNodeCode());
            temp.setDeploymentId(context.getDeployId());
            if (StringUtils.isNotBlank(temp.getCallbackContent())) {
                result.add(temp);
            }
        }
        return result;
    }


}
